home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
301-325
/
disk_319
/
cnewssrc
/
cnews.orig.lzh
/
input
/
newsspool.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-06-27
|
6KB
|
291 lines
/*
* newsspool - copy incoming news into incoming directory
*
* The -i option relies on the parent setting (and exporting) $PATH.
*
* $Log$
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include "libc.h"
#include "news.h"
#include "config.h"
#ifndef lint
static char RCSid[] = "$Header$";
#endif
#ifndef MAXTRIES
#define MAXTRIES 100 /* limit on attempts to make links */
#endif
int debug = 0;
char *progname;
extern void error(), exit();
#ifdef UTZOOERR
extern char *mkprogname();
#else
#define mkprogname(a) (a)
#endif
char buf[BUFSIZ*16]; /* try to get a batch in a few gulps */
int immed = 0; /* try an immediate newsrun? */
void process();
FILE *outopen();
void outclose();
extern time_t time();
char *outname();
/*
- main - parse arguments and handle options
*/
main(argc, argv)
int argc;
char *argv[];
{
int c;
int errflg = 0;
FILE *in;
struct stat statbuf;
extern int optind;
extern char *optarg;
extern FILE *efopen();
void process();
progname = mkprogname(argv[0]);
while ((c = getopt(argc, argv, "id")) != EOF)
switch (c) {
case 'i': /* try immediate newsrun */
immed++;
break;
case 'd': /* Debugging. */
debug++;
setbuf(stderr, (char *)NULL);
break;
case '?':
default:
errflg++;
break;
}
if (errflg) {
fprintf(stderr, "usage: %s [file] ...\n", progname);
exit(2);
}
/* probe to get unprivileged() called if necessary */
(void) ctlfile((char *)NULL);
/* mktemp() uses access(2) [ARGH!] so minimize chances of trouble */
(void) setgid(getegid());
(void) setuid(geteuid());
(void) umask(newsumask());
if (optind >= argc)
process(stdin, "stdin");
else
for (; optind < argc; optind++)
if (STREQ(argv[optind], "-"))
process(stdin, "-");
else {
in = efopen(argv[optind], "r");
if (fstat(fileno(in), &statbuf) < 0)
error("can't fstat `%s'", argv[optind]);
if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
error("`%s' is directory!", argv[optind]);
process(in, argv[optind]);
(void) fclose(in);
}
if (immed) {
execlp("newsrun", "newsrun", (char *)NULL);
error("attempt to run newsrun failed!", "");
}
exit(0);
}
/*
* process - process input file
*/
/* ARGSUSED */
void
process(in, inname)
FILE *in;
char *inname;
{
register int count;
register int firstblock;
FILE *out;
register char *p;
register int n;
char *name;
name = outname();
out = outopen(name);
/* do the copying */
firstblock = 1;
while ((count = fread(buf, sizeof(char), sizeof(buf), in)) > 0) {
if (firstblock) {
n = cunskip(buf, count);
p = buf + n;
count -= n;
firstblock = 0;
} else
p = buf;
n = fwrite(p, sizeof(char), count, out);
if (n != count)
error("write error in output to `%s'", name);
}
outclose(out, name);
}
/*
- outname - construct name for the temporary output file
*/
char *
outname()
{
register char *p;
p = strsave(fullartfile("in.coming/nspool.XXXXXX"));
mktemp(p);
return(p);
}
/*
- outopen - acquire an output file
*/
FILE *
outopen(name)
char *name;
{
FILE *f;
f = fopen(name, "w");
if (f == NULL)
error("unable to create temporary `%s'", name);
if (debug)
fprintf(stderr, "output into %s\n", name);
return(f);
}
/*
- outclose - close output file, moving it to the right place
*
* Names are based on the current time in hopes of keeping input in order.
*/
void
outclose(f, tmpname)
FILE *f;
char *tmpname;
{
register char *p;
register char *name;
register int ntries;
time_t now;
extern int errno;
if (fclose(f) == EOF)
error("fclose error on file `%s'", tmpname);
p = fullartfile("in.coming/");
name = emalloc(strlen(p) + 20); /* plenty for a number */
(void) strcpy(name, p);
p = name + strlen(name);
ntries = 0;
for (;;) {
now = time((time_t *)NULL);
sprintf(p, "%ld", now);
if (debug)
fprintf(stderr, "trying renaming to %s\n", name);
if (link(tmpname, name) >= 0)
break; /* NOTE BREAK OUT */
if (errno != EEXIST) /* something strange is wrong */
error("unable to link `%s'", tmpname);
errno = 0;
if (ntries > MAXTRIES) /* sanity check */
error("too many attempts to link `%s'", tmpname);
if (debug)
fprintf(stderr, "failed\n");
sleep(2); /* avoid rumored race in 1-sec sleep */
ntries++;
}
if (debug)
fprintf(stderr, "succeeded\n");
(void) unlink(tmpname);
}
/*
- cunskip - inspect block for silly #! cunbatch headers
*/
int /* number of chars at start to skip */
cunskip(bufp, count)
char *bufp;
int count;
{
static char goop[] = "cunbatch";
# define GOOPLEN (sizeof(goop)-1) /* strlen(goop) */
static char goop2[] = "c7unbatch";
# define GOOP2LEN (sizeof(goop2)-1) /* strlen(goop2) */
register char *p;
register int nleft;
nleft = count;
p = bufp;
if (nleft < 2) /* no room for a header */
return(0);
if (*p++ != '#' || *p++ != '!') /* doesn't start with #! */
return(0);
nleft -= 2;
/* skip space */
while (nleft > 0 && (*p == ' ' || *p == '\t')) {
p++;
nleft--;
}
/* recognize headers (the +1s ensure room for the newline) */
if (nleft >= GOOPLEN+1 && STREQN(p, goop, GOOPLEN)) {
p += GOOPLEN;
nleft -= GOOPLEN;
} else if (nleft >= GOOP2LEN+1 && STREQN(p, goop2, GOOP2LEN)) {
p += GOOP2LEN;
nleft -= GOOP2LEN;
} else /* no header */
return(0);
/* skip more space */
while (nleft > 0 && (*p == ' ' || *p == '\t')) {
p++;
nleft--;
}
if (nleft == 0 || *p++ != '\n') /* didn't end properly */
return(0);
return(p - bufp);
}
/*
- unprivileged - drop setuidness if configuration is overridden
*/
void
unprivileged()
{
setgid(getgid());
setuid(getuid());
}